package socket

import (
	"bytes"
	"encoding/binary"
	"go-client/utils"
	"net"
	"time"
)

// SocketSender 从collect channel接收数据，发送至socket
func SocketSender(senderSocketAddr string, dataChan <-chan string) {

	// Step1：corner case
	if len(senderSocketAddr) == 0 {
		utils.Logger.Error("【socket_sender】Sender socket addr is empty")
		return
	}

	// 建立socket连接
	timeout := 5 * time.Second
	conn, errConn := net.DialTimeout("tcp", senderSocketAddr, timeout)
	if conn != nil {
		defer conn.Close()
	}

	// Step2：读取channel中的数据并进行socket发送
	for data := range dataChan {
		dataToSend := data

		utils.Logger.Infof("【socket_sender】Data Send: %v, Data Length: %d", dataToSend, len(dataToSend))

		// 重新建立socket连接
		if errConn != nil || conn == nil {
			utils.Logger.Warnf("【socket_sender】Error connecting to NMS-LOAD. Write data to project local. err: %v", errConn)
			// 重新建立连接
			conn, errConn = net.DialTimeout("tcp", senderSocketAddr, timeout)
			continue
		}
		// socket写入逻辑
		dataToSendContentInBytes := []byte(dataToSend)
		// 获取待发送报文长度
		dataToSendLenInBytes, errLen := intToBytes(len(dataToSendContentInBytes))
		if errLen != nil || dataToSendLenInBytes == nil {
			utils.Logger.Errorf("【socket_sender】Error converting data length to little end bytes.  err: %v", errLen)
			continue
		}
		// 发送报文长度
		_, errWriteLen := conn.Write(dataToSendLenInBytes)
		// 发送报文本身
		_, errWriteContent := conn.Write(dataToSendContentInBytes)

		if errWriteLen != nil || errWriteContent != nil {
			utils.Logger.Errorf("【socket_sender】Error sending data to NMS-LOAD, write data to project local. length err: %v. content err: %v", errWriteLen, errWriteContent)
			// 重新建立连接
			conn, errConn = net.DialTimeout("tcp", senderSocketAddr, timeout)
		} else {
			utils.Logger.Info("【socket_sender】Send to NMS-LOAD successfully")
		}
	}

}

// 为适配 Netty LengthFieldBasedFrameDecoder接收协议，长度按小端转成字节
func intToBytes(n int) ([]byte, error) {
	buf := new(bytes.Buffer)
	// 按小端序写入
	err := binary.Write(buf, binary.LittleEndian, int32(n))
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
